`include "common_header.verilog"

//  *************************************************************************
//  File : p8264_bip_check_top.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited.
//  Copyright (c) 2008 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Denis Poverennyy
//  info@morethanip.com
//  *************************************************************************
//  Description : BIP Checker with EEE82 support (down counter derive)
//  Version     : $Id: p8264_bip_check_top.v,v 1.3 2017/04/13 16:02:40 wt Exp $
//  *************************************************************************

module p8264_bip_check_top (

        reset,          
        clk,            
        data_val,       
        marker_dval,    
        data_in_0,      
        data_in_1,      
        data_in_2,      
        data_in_3,      
        sh_in_0,        
        sh_in_1,        
        sh_in_2,        
        sh_in_3,
        bip8_err,
        align_done_l        
        
`ifdef MTIPPCS82_EEE_ENA         
        ,
        vl_match_num_0,                    
        vl_match_num_1,
        vl_match_num_2,
        vl_match_num_3,
        rx_down_count_0,
        rx_down_count_1,
        rx_down_count_2,
        rx_down_count_3
`endif
                                );

input           reset;          //  async active high reset
input           clk;            //  system clock
input           data_val;       //  Data and Sync header valid
input           marker_dval;    //  Pulse at the expected Alignment Marker position
input   [63:0]  data_in_0;      //  Data input for Lane 0
input   [63:0]  data_in_1;      //  Data input for Lane 1
input   [63:0]  data_in_2;      //  Data input for Lane 2
input   [63:0]  data_in_3;      //  Data input for Lane 3
input   [1:0]   sh_in_0;        //  Sync header for Lane 0
input   [1:0]   sh_in_1;        //  Sync header for Lane 1
input   [1:0]   sh_in_2;        //  Sync header for Lane 2
input   [1:0]   sh_in_3;        //  Sync header for Lane 3
input   [3:0]  align_done_l;    // alignment done per lane
`ifdef MTIPPCS82_EEE_ENA 
input   [3:0]   vl_match_num_0; // virtual lane 0 id (one hot coding)
input   [3:0]   vl_match_num_1; // virtual lane 0 id (one hot coding)
input   [3:0]   vl_match_num_2; // virtual lane 0 id (one hot coding)
input   [3:0]   vl_match_num_3; // virtual lane 0 id (one hot coding)
output  [7:0]   rx_down_count_0;//The value that results from the bit-wise exclusive-OR of the Count Down (CD3) byte and the M0
output  [7:0]   rx_down_count_1;//byte of the current Rapid Alignment Marker payload (see 82.2.8a).
output  [7:0]   rx_down_count_2;
output  [7:0]   rx_down_count_3;

`endif
output  [3:0]   bip8_err;       //  bip error (one clock pulse) 


//-------------------------------------
// Output Signals
//-------------------------------------
wire    [3:0]   bip8_err;

`ifdef MTIPPCS82_EEE_ENA 
wire     [7:0]   rx_down_count_0;
wire     [7:0]   rx_down_count_1;
wire     [7:0]   rx_down_count_2;
wire     [7:0]   rx_down_count_3;
`endif

//-------------------------------------
// Internal Signals
//------------------------------------- 
wire    [64*4 -1:0]     data_in_vec =  {data_in_3,data_in_2,data_in_1,data_in_0};
wire    [2*4  -1:0]     sh_in_vec = {sh_in_3,sh_in_2,sh_in_1,sh_in_0};
`ifdef MTIPPCS82_EEE_ENA
wire    [8*4  -1:0]     rx_down_count_vec;      // Concatenated down conter for all lanes 
wire    [4*4 - 1:0]     vl_match_num_vec ={vl_match_num_3, vl_match_num_2, vl_match_num_1, vl_match_num_0};
assign {rx_down_count_3,rx_down_count_2,rx_down_count_1,rx_down_count_0} = rx_down_count_vec;
`endif


genvar gi;
generate for(gi=0; gi< 4; gi=gi+1)
begin:genfifo
        
p8264_bip_check U_BIP_CHECK(

        .reset                  (reset),
        .clk                    (clk),
        .data_val               (data_val),
        .marker_dval            (marker_dval),
        .data_in                (data_in_vec[gi * 64 + 64-1:gi * 64]),  // [63:0]
        .sh_in                  (sh_in_vec  [gi * 2 + 2- 1:gi*2]),           // [1:0]
        .align_done             (align_done_l[gi]),
`ifdef MTIPPCS82_EEE_ENA
 
        .rx_down_count          (rx_down_count_vec[gi * 8 + 8 - 1:gi*8]),
        .vl_match_num           (vl_match_num_vec [gi * 4 + 4 - 1:gi*4]),
`endif
        .bip8_err               (bip8_err[gi]));
end
endgenerate



// ----------
// ASSERTIONS
// ----------

`ifdef MTIPASSERTIONS
// synthesis translate_off
// synopsys translate_off
reg nc_asrt_is25;

always @(posedge clk or posedge reset)
begin:assertions
        
        if( reset == 1'b 1 )
        begin
                nc_asrt_is25 = 1'b 0;
        end
        else
        begin
            begin
                
                        // suppress message for 25G RSFEC which uses a fixed constant instead of BIP to avoid false assertion message of 40G.
                        // (then also suppessing this 1 out of 256 values from asserting in 40G but that is fine for purpose 
                        // of this warning message generation)
                        // bip8_err asserts the clock following marker_dval
                nc_asrt_is25 <= ( marker_dval==1'b 1 && data_in_vec[31:24] == 8'h 33 && data_in_vec[63:56] == ~(8'h 33) ) ? 1'b 1 : 1'b 0;
                
                if(bip8_err != 4'b0 && nc_asrt_is25 == 1'b 0)
                begin
                        $display("%t ASSERT [p8264_bip_check_top:%m]: WARNING: Receive BIP Error for 40G %04b",$time, bip8_err);
                end
            
            end
            
        end
        
end

// synopsys translate_on
// synthesis translate_on
`endif





endmodule // module p8264_bip_check_top
